#[macro_use] mod log_macro;
// mod log_out;
mod log_config;
mod log_out;

#[cfg(feature = "table")]
mod log_table;
#[cfg(feature = "table")]
pub use log_table::*;

pub use log_config::{set_level,set_prefix,show_time,show_file_line,output_to_file};
pub use log_config::{get_level,get_prefix,output};
pub use log_config::{Level,DEBUG,INFO,WARN,ERROR,PANIC};
pub use log_out::*;

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use crate::{show_time, show_file_line, set_prefix, set_level, output_to_file, INFO, Level, log_prefix, PrintTable};
    use crate::log_config::close_output;

    #[test]
    fn log_config() {
        //Set log level, default:Debug
         set_level( INFO);
        //Set the log output prefix, default:"wd_log"
         set_prefix("WDLOG");
        //Whether to display the print time, default:true
         show_time(false);
        //Whether to display the location, default:true
         show_file_line(false);
        //Set output to a file, default:stdout
         output_to_file("./log.txt").expect("file open failed");
         log_debug_ln!("this is file output");
        //close output to std out
        close_output();
    }
    #[test]
    fn log_print(){
         log_debug!("{}","hello world");
         log_debug_ln!("{}","hello world");
         log_info!("{}","hello world");
         log_info_ln!("{}","hello world");
         log_warn!("{}","hello world");
         log_warn_ln!("{}","hello world");
         log_error!("{}","hello world");
         log_error_ln!("{}","hello world");
    }
    #[test]
    #[should_panic]
    fn log_panic(){
         log_panic!("{}","hello world");
    }
    #[test]
    fn error(){
        let result = Err("hello");
        let _res:Option<()> =  res_error!(result);
        let _res:Option<()> =  res_error_ln!(result);

        let _res:Option<()> =  res_error!(result;"this is {}","error");
        let _res:Option<()> =  res_error_ln!(result;"this is {}","error");

        let result:Result<&str,&str> = Ok("world");
        let res:Option<&str> =  res_error!(result);
        assert_eq!(res,Some("world"))
    }
    #[test]
    #[should_panic]
    fn res_panic(){
        let result:Result<&str,&str> = Ok("hello");
        let res =  res_panic!(result;"succes");
        println!("{}",res);
        let result = Err("hello");
        //It can lead to panic
        let _ =  res_panic!(result;"this is {}","error");
    }
    #[test]
    fn test_level(){
        let level = Level::from("inFO");
        println!("level {}",level.as_u8())
    }

    #[test]
    fn test_log_output(){
        log_prefix("hello world")
            .prefix("123")
            .prefix("2022-01-02 00:00:00")
            .prefix("74654313896493")
            .field("key","value")
            .field("count",1000)
            .fields(HashMap::from([
                ( "key1".to_string(),"value1".to_string()),
                ("key2".to_string(),"value2".to_string())]))
            .info("info content")
    }

    #[cfg(feature = "table")]
    #[test]
    fn test_table(){
        use super::{Tabled};

        #[derive(Tabled)]
        struct Language {
            name: &'static str,
            designed_by: &'static str,
            invented_year: usize,
        }

        let languages = vec![
            Language{
                name: "C",
                designed_by: "Dennis Ritchie",
                invented_year: 1972
            },
            Language{
                name: "Go",
                designed_by: "Rob Pike",
                invented_year: 2009
            },
            Language{
                name: "Rust",
                designed_by: "Graydon Hoare",
                invented_year: 2010
            },
        ];

        languages.print_table();
    }
}
